﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PhoneApp1
{
    using System;

        class Algorithem
        {


            private static int ENTITLED_INCOME_2013 = 10914;
            //private static  int VALUE_OF_1_POINT_2012 = 215;
            private static int VALUE_OF_1_POINT_2013 = 218;
            //private static  int PENSION_TOP_SALARY_2012 = 47600;
            private static int PENSION_TOP_SALARY_2013 = 35312;
            private static int roofOfKerenHishtalmutWithoutTaxes = 15712;
            private volatile static Algorithem instance;


            public double points = 2.25;
            public double salaryWithoutPension;
            private double baseSalary;
            private double socialPaymentSalary;
            private double brutoSalary;
            private double taxesSalary;
            private double Pension;
            public double PensionPercentage;
            private double KerenHishtalmut;
            private double SocialPayment;
            double InTheBank;
            public double driving;
            public bool aboveCeilinOfKerenHishtalmut = false;
            public double kerenPercantage;
            private double incomeTax;
            private double healthTaxAndSocialSecurityStep = 4809;
            private double healthTaxAndSocialSecurityTopTaxIncome = 40790;
            private double healthTax;
            private double socialSecurity;
            private bool leasing;
            private double carPrice;
            private bool hybrid;
            private double CAR_PRICE_ROOF = 490020;
            private double monthlyPaymentForCar = 0.0;

            public double GetIncomeTax()
            {
                return incomeTax;
            }

            public double getsocialSecurity()
            {
                return socialSecurity;
            }

            public double GetHealthTax()
            {
                return healthTax;
            }

            public double GetPenstionPayment()
            {
                return Pension;
            }

            public double GetTrainingFund()
            {
                return KerenHishtalmut;
            }

            private Algorithem()
            {
                kerenPercantage = 0.025;
                PensionPercentage = 0.05; // this can be changed
                driving = 0;
                salaryWithoutPension = 0;
                for (int i = 0; i < steps.GetLength(0); i++)
                {
                    steps[i, 2] = setSumedIrs(i);
                }

            }

            // singleton
            public static Algorithem GetInstance()
            {
                if (instance == null)
                {
                    lock ("lock")
                    {
                        if (instance == null)
                        {
                            instance = new Algorithem();
                        }
                    }
                }
                return instance;

            }


            public double Calculate()
            {

                // דבר ראשון יש לנו שכר יסוד
                // ממנו נחסר תשלום לחברה שלנו עבור ליסינג
                if (isLeasing())
                {
                    socialPaymentSalary = baseSalary - monthlyPaymentForCar;
                }
                else
                {
                    socialPaymentSalary = baseSalary;
                }

                brutoSalary = baseSalary + salaryWithoutPension;
                if (isLeasing())
                {
                    brutoSalary -= monthlyPaymentForCar;
                }
                else
                {
                    // נוסיף לברוטו נסיעות במידה ואנחנו לא לוקחים ליסינג
                    salaryWithoutPension += driving;
                    brutoSalary += driving;
                }
                //והנה החלק מהמשכורת שהוא לא לסוציאלי (כמו שעות נוספות גלובאליות 



                //setSumedIrs(int index)שכר למס הכנסה
                //פה נכנס המס על הליסינג וגם עוד קרן השתלמות מעל התקרה
                // TODO: קרן השתלמות מעל התקרה
                if (isLeasing())
                {
                    taxesSalary = brutoSalary + calculateLeasingPayment();
                }
                else
                {
                    taxesSalary = brutoSalary;
                }
                //now i limit the keren hishtalmut to 15712.


                //this is how much the worker pay from his salary
                // צריך להוסיף את הקונספט של קרן השתלמות מעל התקרה
                KerenHishtalmut = GetKerenHishtalmut();

                //חישוב מס הכנסה
                incomeTax = IRS();

                Pension = GetPension();


                calculateHealthTax();
                calculateSocialSecurity();
                SocialPayment = GetSocialPayment();

                InTheBank = brutoSalary - incomeTax - KerenHishtalmut - Pension - calculateKupatGemelLeatzmaim() - SocialPayment;

                return InTheBank; // hilan will be different because in hilan the
                // employer put the above keren hishtalmut
                // money in the fund, and I put it in the bank
            }

            private double calculateLeasingPayment()
            {
                if (carPrice > CAR_PRICE_ROOF)
                {
                    carPrice = CAR_PRICE_ROOF;
                }
                else if (carPrice < 0)
                {
                    return 0;
                }

                double payment = carPrice * 0.0248;
                if (isHybrid())
                {
                    payment -= 540;
                }
                return payment;
            }

            public double GetInTheBank()
            {
                return InTheBank;
            }

            // public void SetTravelRefunds(double travelRefunds){
            // this.salary = this.salary + travelRefunds;
            // }

            public double GetSocialAlocation()
            {
                return KerenHishtalmut + Pension;
            }

            public double GetTaxes()
            {
                return IRS() + SocialPayment;
            }

            private double GetSocialPayment()
            {
                return healthTax + socialSecurity;
            }

            private void calculateHealthTax()
            {
                if (taxesSalary < healthTaxAndSocialSecurityStep)
                    healthTax = taxesSalary * 0.031;
                else if (taxesSalary < healthTaxAndSocialSecurityTopTaxIncome)
                    healthTax = healthTaxAndSocialSecurityStep * 0.031
                            + (taxesSalary - healthTaxAndSocialSecurityStep) * 0.05;
                else
                    healthTax = (healthTaxAndSocialSecurityStep * 0.031)
                            + (healthTaxAndSocialSecurityTopTaxIncome - healthTaxAndSocialSecurityStep)
                            * 0.05;
            }

            public double calculateKupatGemelLeatzmaim()
            {
                //פה אני מפריש כסף לפנסיה מהתוספות למשכורת
                if (salaryWithoutPension < 8200)
                {
                    return salaryWithoutPension * 0.05;
                }
                else
                {
                    return 8200 * 0.05;
                }

            }
            private void calculateSocialSecurity()
            {
                // חישוב מס ביטוח לאומי
                // יsetSumedIrs(int index)ש מדרגות בהפרשות לביטוח לאומי
                // עד המדרגה הראשונה מופרת 0.4 אחוז
                if (taxesSalary < healthTaxAndSocialSecurityStep)
                {
                    socialSecurity = taxesSalary * 0.004;
                    //  (40790ממשכורת שנמוכה מהתקרה (נכון ל2012 מדובר ב
                    //   יופרשו רק 7 אחוז מהמשכורת מהחלק שמעל
                    // מהמדרגה הראשונה 
                }
                else if (taxesSalary < healthTaxAndSocialSecurityTopTaxIncome)
                {
                    socialSecurity = healthTaxAndSocialSecurityStep * 0.004
                            + (taxesSalary - healthTaxAndSocialSecurityStep) * 0.07;
                }
                else
                {
                    // טוב יש גבול לעד כמה אפשר לחלוב לכן אם אתה מרוויח הרבה אז מרחמים עליך
                    socialSecurity = (healthTaxAndSocialSecurityStep * 0.004)
                            + (healthTaxAndSocialSecurityTopTaxIncome - healthTaxAndSocialSecurityStep)
                            * 0.07;
                }
            }


            public double[,] steps = {
			
			{10,5280,0},
			{14,9010,0},
			{21,14000,0},
			{31,20000,0},
			{34,41830,0},
			{48,67630,0},
			{50,0,0}
			};

            public double setSumedIrs(int index)
            {
                double sum = 0;

                for (int j = 0; j <= index; j++)
                {
                    if (j == 0)
                    {
                        sum += (double)(steps[j, 0] * (steps[j, 1])) * 0.01;
                    }
                    else
                    {
                        sum += (double)(steps[j, 0] * (steps[j, 1] - steps[j - 1, 1])) * 0.01;
                    }
                }
                return sum;
            }

            private double IRS()
            {
                double taxPercent;
                double IrsToPay;
                // מדרגות מס וכל השיט
                if ((taxesSalary) < steps[0, 1])
                {
                    taxPercent = steps[0, 0] / 100;
                    IrsToPay = (taxesSalary) * taxPercent;
                }
                else if ((taxesSalary) < steps[1, 1])
                {
                    taxPercent = steps[1, 0] / 100;
                    IrsToPay = ((taxesSalary) - steps[0, 1]) * taxPercent + setSumedIrs(0);
                }
                else if ((taxesSalary) < steps[2, 1])
                {
                    taxPercent = steps[2, 0] / 100;
                    IrsToPay = ((taxesSalary) - steps[1, 1]) * taxPercent + setSumedIrs(1);
                }
                else if ((taxesSalary) < steps[3, 1])
                {
                    taxPercent = steps[3, 0] / 100;
                    IrsToPay = ((taxesSalary) - steps[2, 1]) * taxPercent + setSumedIrs(2);
                }
                else if ((taxesSalary) < steps[4, 1])
                {
                    taxPercent = steps[4, 0] / 100;
                    IrsToPay = ((taxesSalary) - steps[3, 1]) * taxPercent + setSumedIrs(3);
                }
                else if ((taxesSalary) < steps[5, 1])
                {
                    taxPercent = steps[5, 0] / 100;
                    IrsToPay = ((taxesSalary) - steps[4, 1]) * taxPercent + setSumedIrs(4);
                }
                else
                {
                    taxPercent = steps[6, 0] / 100;
                    IrsToPay = ((taxesSalary) - steps[5, 1]) * taxPercent + setSumedIrs(5);
                }

                //מס הכנסה מחזיר לך חמש אחוז על הכסף שאתה מפריש לפנסיה.
                // אבל עד תקרת משכורת של 8600
                if (GetPension() < (ENTITLED_INCOME_2013 * 0.05))
                {
                    IrsToPay = IrsToPay - 0.35 * GetPension() - calculateKupatGemelLeatzmaim() * taxPercent;
                }
                else
                {
                    IrsToPay = IrsToPay - 0.35 * ENTITLED_INCOME_2013 * 0.05 - calculateKupatGemelLeatzmaim() * taxPercent;
                }

                //והכי חשוב זה נקודות זיכוי
                IrsToPay = IrsToPay - points * VALUE_OF_1_POINT_2013;
                if (IrsToPay < 0)
                    IrsToPay = 0;

                return IrsToPay;
            }


            private double GetPension()
            {
                if (socialPaymentSalary < PENSION_TOP_SALARY_2013)
                {
                    return PensionPercentage * socialPaymentSalary;
                }
                else
                {
                    return PensionPercentage * PENSION_TOP_SALARY_2013;
                }
            }

            public double GetKerenHishtalmut()
            {
                if (socialPaymentSalary > roofOfKerenHishtalmutWithoutTaxes)
                {
                    return roofOfKerenHishtalmutWithoutTaxes * kerenPercantage;
                }
                else
                {
                    return socialPaymentSalary * kerenPercantage;
                }
            }

            public bool isLeasing()
            {
                return leasing;
            }

            public void setLeasing(bool leasing)
            {
                this.leasing = leasing;
            }

            public bool isHybrid()
            {
                return hybrid;
            }

            public void setHybrid(bool hybrid)
            {
                this.hybrid = hybrid;
            }

            public double getCarPrice()
            {
                return carPrice;
            }

            public void setCarPrice(double carPrice)
            {
                this.carPrice = carPrice;
            }

            public void setMonthlyPaymentForCar(double monthlyPaymentForCar)
            {
                this.monthlyPaymentForCar = monthlyPaymentForCar;
            }

            public double getMonthlyPaymentForCar()
            {
                return monthlyPaymentForCar;
            }

            public void setBaseSalary(double baseSalary)
            {
                this.baseSalary = baseSalary;
            }


        }
    
}
